package com.sun.umbrella.service.bns.user.impl;

import com.alibaba.fastjson.JSON;
import com.sun.core.enums.BaseBizEnum;
import com.sun.core.enums.BaseErrorEnum;
import com.sun.core.enums.DeletedEnum;
import com.sun.core.enums.YnEnum;
import com.sun.core.ex.BusinessCheckFailException;
import com.sun.core.ex.BusinessProcessFailException;
import com.sun.core.web.page.PageUtil;
import com.sun.star.base.util.BeanUtil;
import com.sun.umbrella.dao.OauthUserMapper;
import com.sun.umbrella.dao.RoleInfoMapper;
import com.sun.umbrella.dao.UserEtcMapper;
import com.sun.umbrella.dao.UserRoleRelationMapper;
import com.sun.umbrella.domain.bo.RoleInfoBO;
import com.sun.umbrella.domain.bo.UserEtcBO;
import com.sun.umbrella.domain.entity.OauthUserDO;
import com.sun.umbrella.domain.entity.UserEtcDO;
import com.sun.umbrella.domain.entity.UserRoleRelationDO;
import com.sun.umbrella.domain.enums.UserEnableEnum;
import com.sun.umbrella.domain.query.RoleInfoQuery;
import com.sun.umbrella.domain.query.UserEtcQuery;
import com.sun.umbrella.domain.vo.UserEtcSaveVO;
import com.sun.umbrella.domain.vo.UserEtcUpdateVO;
import com.sun.umbrella.domain.vo.UserEtcVO;
import com.sun.umbrella.domain.bo.UserLoginSuccessBO;
import com.sun.umbrella.manager.utils.PasswordUtil;
import com.sun.umbrella.service.bns.user.UserEtcService;
import com.sun.umbrella.session.ContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * @author Jay
 * @version v1.0
 * @description 用户信息相关逻辑
 * @date 2018-04-26 15:29
 */
@Slf4j
@Service
public class UserEtcServiceImpl implements UserEtcService {


    @Autowired
    private UserEtcMapper userEtcMapper;

    @Autowired
    private OauthUserMapper oauthUserMapper;

    @Autowired
    private RoleInfoMapper roleInfoMapper;

    @Autowired
    private UserRoleRelationMapper userRoleRelationMapper;

    @Autowired
    private ContextHolder contextHolder;


    /**
     * 分页查询用户
     *
     * @param userEtcQuery
     * @return
     */
    @Override
    public Page<UserEtcVO> queryUserPageList(UserEtcQuery userEtcQuery, Pageable pageable) {
        // 查询总量
        int count = userEtcMapper.countUserEtcList(userEtcQuery);
        if (BaseBizEnum.ZERO.getKey() == count) {
            return PageUtil.newEmptyPage(pageable);
        }
        // 封装分页参数
        PageUtil.fillParam(userEtcQuery, pageable);
        List<UserEtcBO> userEtcDOList = userEtcMapper.queryUserEtcList(userEtcQuery);
        log.info("分页查询用户信息返回值为:{}", JSON.toJSONString(userEtcDOList));
        List<UserEtcVO> userEtcVOList = BeanUtil.copyList(userEtcDOList, UserEtcVO.class);
        if (CollectionUtils.isEmpty(userEtcVOList)) {
            return PageUtil.newEmptyPage(pageable);
        }
        return PageUtil.newPage(userEtcVOList, pageable, count);
    }


    /**
     * 保存用户信息
     *
     * @param userEtcSaveVO
     * @return
     */
    @Transactional(rollbackFor = BusinessProcessFailException.class)
    @Override
    public Boolean saveUser(UserEtcSaveVO userEtcSaveVO) {
        // 参数校验
        this.checkSaveUserParam(userEtcSaveVO);
        OauthUserDO oauthUserDO = this.fillOauthUserDO(userEtcSaveVO);
        // 插入用户密码表
        if (oauthUserMapper.insert(oauthUserDO) != BaseBizEnum.FIRST.getKey()) {
            throw new BusinessProcessFailException("保存用户信息失败", BaseErrorEnum.SAVE_ERROR.getCode());
        }
        // 转换
        UserEtcDO userEtcDO = this.fillUserEtcDOWhenInsert(userEtcSaveVO);
        userEtcDO.setUserId(oauthUserDO.getId());
        // 插入um_user_etc表
        if (userEtcMapper.insertUserEtc(userEtcDO) != BaseBizEnum.FIRST.getKey()) {
            throw new BusinessProcessFailException("保存用户信息失败", BaseErrorEnum.SAVE_ERROR.getCode());
        }
        UserRoleRelationDO userRoleRelationDO = this.fillUserRoleRelationDO(userEtcDO);
        // 保存角色和用户之前的关系
        if (userRoleRelationMapper.insert(userRoleRelationDO) != BaseBizEnum.FIRST.getKey()) {
            throw new BusinessProcessFailException("保存用户信息失败", BaseErrorEnum.SAVE_ERROR.getCode());
        }
        return Boolean.TRUE;
    }

    /**
     * 更新用户信息
     *
     * @param userEtcUpdateVO
     * @return
     */
    @Transactional(rollbackFor = BusinessProcessFailException.class)
    @Override
    public Boolean updateUser(UserEtcUpdateVO userEtcUpdateVO) {
        // 参数校验
        this.checkUpdateUserParam(userEtcUpdateVO);
        // 转换
        UserEtcDO userEtcDO = this.fillUserEtcDOWhenUpdate(userEtcUpdateVO);
        // 更新um_user_etc表的对应记录
        if (userEtcMapper.updateById(userEtcDO) != BaseBizEnum.FIRST.getKey()) {
            throw new BusinessProcessFailException("更新用户信息失败", BaseErrorEnum.UPDATE_ERROR.getCode());
        }
        // 查询该条记录的userId
        UserEtcDO data = userEtcMapper.selectById(userEtcUpdateVO.getId());
        if (data == null || data.getUserId() == null) {
            throw new BusinessProcessFailException("数据异常", BaseErrorEnum.UPDATE_ERROR.getCode());
        }
        Integer modifier = this.getUserId();
        // 更新角色和用户关联关系对应的记录
        if (userRoleRelationMapper.updateByUserId(data.getUserId(), modifier, userEtcUpdateVO.getRoleId()) != BaseBizEnum.FIRST.getKey()) {
            throw new BusinessProcessFailException("更新用户信息失败", BaseErrorEnum.UPDATE_ERROR.getCode());
        }
        // 判断记录是否存在
        OauthUserDO oauthUserDO = oauthUserMapper.selectById(data.getUserId());
        if (oauthUserDO == null) {
            throw new BusinessProcessFailException("更新用户信息失败", BaseErrorEnum.UPDATE_ERROR.getCode());
        }
        // 判断密码是否为空，如果密码为空，则说明不需要更新密码，否则更新密码
        String password = userEtcUpdateVO.getPassword();
        if (!StringUtils.isEmpty(password)) {
            String passwordStr = PasswordUtil.makePassword(password, oauthUserDO.getSalt());
            if (oauthUserMapper.updatePasswordById(passwordStr, data.getUserId()) != BaseBizEnum.FIRST.getKey()) {
                throw new BusinessProcessFailException("更新用户密码失败", BaseErrorEnum.UPDATE_ERROR.getCode());
            }
        }
        return Boolean.TRUE;
    }

    /**
     * 更新用户状态 启用、禁用
     *
     * @param enable
     * @return
     */
    @Transactional(rollbackFor = BusinessProcessFailException.class)
    @Override
    public Boolean updateUserEnable(Integer id, Integer enable) {
        if (enable == null) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "enable不能为空");
        }
        if (id == null) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "id不能为空");
        }
        if (enable != UserEnableEnum.USER_ENABLE.getKey() && enable != UserEnableEnum.USER_NOE_ENABLE.getKey()) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "enable传入值不合法");
        }
        // 更新用户状态
        if (oauthUserMapper.updateEnableById(id, enable) != BaseBizEnum.FIRST.getKey()) {
            throw new BusinessProcessFailException("更新用户状态失败", BaseErrorEnum.UPDATE_ERROR.getCode());
        }
        return Boolean.TRUE;
    }

    /**
     * 删除用户
     *
     * @param id
     * @return
     */
    @Transactional(rollbackFor = BusinessProcessFailException.class)
    @Override
    public Boolean deletedUser(Integer id) {
        if (id == null) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "id不能为空");
        }
        // 更新um_oauth2_user表中isDeleted值
        if (oauthUserMapper.updateIsDeletedById(id, DeletedEnum.YES.getKey()) != BaseBizEnum.FIRST.getKey()) {
            throw new BusinessProcessFailException("更新isDeleted值失败", BaseErrorEnum.UPDATE_ERROR.getCode());
        }
        // 更新um_user_etc表中的isDeleted值
        if (userEtcMapper.updateIsDeletedById(id, DeletedEnum.YES.getKey()) != BaseBizEnum.FIRST.getKey()) {
            throw new BusinessProcessFailException("更新isDeleted值失败", BaseErrorEnum.UPDATE_ERROR.getCode());
        }
        return Boolean.TRUE;
    }

    /**
     * 查询所有角色列表
     *
     * @return
     */
    @Override
    public List<RoleInfoBO> queryRoleList() {
        // 查询
        return roleInfoMapper.queryRoleInfoList(new RoleInfoQuery());
    }

    /**
     * 查询用户信息当登录成功后
     *
     * @param userName
     * @return
     */
    @Override
    public UserLoginSuccessBO queryUserInfoWhenLoginSuccess(String userName) {
        if (StringUtils.isEmpty(userName)) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "userName不能为空");
        }
        return oauthUserMapper.queryUserInfoWhenLoginSuccess(userName);
    }

    /**
     * 修改密码
     *
     * @param oldPwd
     * @param newPwd
     * @param confirmPwd
     * @return
     */
    @Transactional(rollbackFor = BusinessProcessFailException.class)
    @Override
    public Boolean changeUserPassword(String oldPwd, String newPwd, String confirmPwd) {
        Integer userId = this.getUserId();
        if (userId == null) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "userId不能为空");
        }
        if (StringUtils.isEmpty(oldPwd) || StringUtils.isEmpty(newPwd) || StringUtils.isEmpty(confirmPwd)) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "密码不能为空");
        }
        if (!newPwd.equals(confirmPwd)) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "两次输入的密码不一致");
        }
        OauthUserDO oauthUserDO = oauthUserMapper.selectById(userId);
        if (oauthUserDO == null) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "该用户不存在");
        }
        String oldPwdStr = PasswordUtil.makePassword(oldPwd,oauthUserDO.getSalt());
        if (!oldPwdStr.equals(oauthUserDO.getPassword())){
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "旧密码错误");
        }
        String password = PasswordUtil.makePassword(newPwd, oauthUserDO.getSalt());
        if (oauthUserMapper.updatePasswordById(password, userId) != BaseBizEnum.FIRST.getKey()) {
            throw new BusinessProcessFailException("更新密码失败", BaseErrorEnum.BNS_CHK_ERROR.getCode());
        }
        return Boolean.TRUE;
    }


    /*=================================================private method====================================================*/


    /**
     * 填充参数
     *
     * @param userEtcUpdateVO
     * @return
     */
    private UserEtcDO fillUserEtcDOWhenUpdate(UserEtcUpdateVO userEtcUpdateVO) {
        UserEtcDO userEtcDO = new UserEtcDO();
        BeanUtil.copyProperties(userEtcUpdateVO, userEtcDO);
        userEtcDO.setGmtModified(new Date());
        userEtcDO.setModifier(this.getUserId());
        return userEtcDO;
    }


    /**
     * 参数校验
     *
     * @param userEtcUpdateVO
     */
    private void checkUpdateUserParam(UserEtcUpdateVO userEtcUpdateVO) {
        if (userEtcUpdateVO == null) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "入参不能为空");
        }
        if (userEtcUpdateVO.getId() == null) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "id不能为空");
        }
        if (StringUtils.isEmpty(userEtcUpdateVO.getRealName())) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "真实姓名不能为空");
        }
        if (StringUtils.isEmpty(userEtcUpdateVO.getRoleName())) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "角色名称不能为空");
        }
        if (StringUtils.isEmpty(userEtcUpdateVO.getUserComments())) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "描述不能为空");
        }
        if (StringUtils.isEmpty(userEtcUpdateVO.getUserEmail())) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "邮箱不能为空");
        }
        if (userEtcUpdateVO.getRoleId() == null) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "角色id不能为空");
        }
    }

    /**
     * 填充参数
     *
     * @param userEtcSaveVO
     * @return
     */
    private OauthUserDO fillOauthUserDO(UserEtcSaveVO userEtcSaveVO) {
        OauthUserDO oauthUserDO = new OauthUserDO();
        oauthUserDO.setIsDeleted(DeletedEnum.NO.getKey());
        oauthUserDO.setGmtCreate(new Date());
        oauthUserDO.setGmtModified(new Date());
        String pwd = PasswordUtil.makePassword(userEtcSaveVO.getPassword(), userEtcSaveVO.getUserName());
        oauthUserDO.setPassword(pwd);
        oauthUserDO.setEnable(UserEnableEnum.USER_ENABLE.getKey());
        oauthUserDO.setSalt(userEtcSaveVO.getUserName());
        oauthUserDO.setUserName(userEtcSaveVO.getUserName());
        return oauthUserDO;
    }

    /**
     * 填充参数
     *
     * @param userEtcSaveVO
     * @return
     */
    private UserEtcDO fillUserEtcDOWhenInsert(UserEtcSaveVO userEtcSaveVO) {
        UserEtcDO userEtcDO = new UserEtcDO();
        BeanUtil.copyProperties(userEtcSaveVO, userEtcDO);
        userEtcDO.setIsDeleted(YnEnum.N.getKey());
        userEtcDO.setCreator(this.getUserId());
        userEtcDO.setModifier(this.getUserId());
        userEtcDO.setGmtCreate(new Date());
        userEtcDO.setGmtModified(new Date());
        return userEtcDO;
    }

    /**
     * 参数校验
     *
     * @param userEtcSaveVO
     */
    private void checkSaveUserParam(UserEtcSaveVO userEtcSaveVO) {
        if (userEtcSaveVO == null) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "入参不能为空");
        }
        if (StringUtils.isEmpty(userEtcSaveVO.getRealName())) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "真实姓名不能为空");
        }
        if (StringUtils.isEmpty(userEtcSaveVO.getRoleName())) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "角色名称不能为空");
        }
        if (StringUtils.isEmpty(userEtcSaveVO.getUserComments())) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "描述不能为空");
        }
        if (StringUtils.isEmpty(userEtcSaveVO.getUserEmail())) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "邮箱不能为空");
        }
        if (StringUtils.isEmpty(userEtcSaveVO.getUserName())) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "用户姓名不能为空");
        }
        if (userEtcSaveVO.getRoleId() == null) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "角色id不能为空");
        }
        if (StringUtils.isEmpty(userEtcSaveVO.getPassword())) {
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(), "密码不能为空");
        }
    }


    /**
     * 参数填充
     *
     * @param userEtcDO
     * @return
     */
    private UserRoleRelationDO fillUserRoleRelationDO(UserEtcDO userEtcDO) {
        UserRoleRelationDO userRoleRelationDO = new UserRoleRelationDO();
        userRoleRelationDO.setCreator(this.getUserId());
        userRoleRelationDO.setModifier(this.getUserId());
        userRoleRelationDO.setIsDeleted(DeletedEnum.NO.getKey());
        userRoleRelationDO.setGmtCreate(new Date());
        userRoleRelationDO.setGmtModified(new Date());
        userRoleRelationDO.setRoleId(userEtcDO.getRoleId());
        userRoleRelationDO.setUserId(userEtcDO.getUserId());
        return userRoleRelationDO;
    }


    /**
     * 获取userId
     *
     * @return
     */
    private Integer getUserId(){
        Integer userId = contextHolder.getSessionContext().getUserId();;
        if (userId == null){
            throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(),"请重新登录");
        }
        return userId;
    }

}
